using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;

namespace LogikBug.Utilities
{
	/// <summary>
	/// Provides helper methods for working with <see cref="Type"/>s.
	/// </summary>
	public class TypeHelper : IReflect
	{
		#region Constructors
		
		/// <summary>
		/// The constructor for the <see cref="TypeHelper"/> class.
		/// </summary>
		/// <param name="type"></param>
		public TypeHelper(Type type)
		{
			Type = type;
		}

		#endregion
		
		#region Properties

		/// <summary>
		/// The current type to provide helper methods for.
		/// </summary>
		public Type Type { get; protected set; }

		#region IReflect Methods

		/// <summary>
		/// Gets the underlying type that represents the <see cref="T:System.Reflection.IReflect"/> object.
		/// </summary>
		/// <returns>
		/// The underlying type that represents the <see cref="T:System.Reflection.IReflect"/> object.
		/// </returns>
		public Type UnderlyingSystemType
		{
			get
			{
				return Type.UnderlyingSystemType;
			}
		}

		#endregion

		#endregion

		#region Methods

		///<summary>
		/// Determines if a <see cref="MethodInfo"/> or <see cref="ConstructorInfo"/> have any parameters.
		///</summary>
		///<param name="info">The method or constructor to check for parameters.</param>
		///<returns>True if the method or constructor has no parameters and False if it does.</returns>
		public static bool IsDefault(MethodBase info)
		{
			ParameterInfo[] parameters = info.GetParameters();
			return (parameters.IsNull() || parameters.Length == 0);
		}

		/// <summary>
		/// Gets the <see cref="Type"/> based off the given name.
		/// </summary>
		/// <param name="fullName">The fully qualified name of the <see cref="Type"/> to retrieve.</param>
		/// <returns>The object's <see cref="Type"/>.</returns>
		public static Type GetType(string fullName)
		{
			return Type.GetType(fullName);
		}

		/// <summary>
		/// Gets a specific type of interface from the given <see cref="MemberInfo"/>.
		/// </summary>
		/// <typeparam name="TAttribute">The type of interface to get.</typeparam>
		/// <param name="type">The <see cref="Type"/> to retrieve the <typeparamref name="TAttribute"/> from.</param>
		/// <returns>
		/// The <typeparamref name="TAttribute"/> attribute, or the default
		/// value if no attribute of <typeparamref name="TAttribute"/> exists.
		/// </returns>
		public static TAttribute GetAttribute<TAttribute>(MemberInfo type)
		{
			TAttribute[] attributes = GetAttributes<TAttribute>(type);

			if (!attributes.IsNull() && attributes.Length != 0)
			{
				return attributes[0];
			}

			return default(TAttribute);
		}

		/// <summary>
		/// Get an array of attributes from the given <see cref="MemberInfo"/>.
		/// </summary>
		/// <typeparam name="TAttribute">The type of attributes to retrieve.</typeparam>
		/// <param name="type">The <see cref="Type"/> to get the attributes from.</param>
		/// <returns>An array of <typeparamref name="TAttribute"/> attributes.</returns>
		public static TAttribute[] GetAttributes<TAttribute>(MemberInfo type)
		{
			return type.GetCustomAttributes(typeof(TAttribute), true) as TAttribute[];
		}

		/// <summary>
		/// Gets the interfaces for a given <see cref="Type"/>.
		/// </summary>
		/// <param name="type">The <see cref="Type"/> to get the interfaces from.</param>
		/// <returns>An array of <see cref="Type"/>.</returns>
		public static Type[] GetInterfaces(Type type)
		{
			return type.GetInterfaces();
		}

		/// <summary>
		/// Gets an interface from the given type by name.
		/// </summary>
		/// <param name="type">The <see cref="Type"/> to retrieve the interface from.</param>
		/// <param name="name">The name of the interface to get.</param>
		/// <returns>The <see cref="Type"/> of interface.</returns>
		public static Type GetInterface(Type type, string name)
		{
			return Array.Find(type.GetInterfaces(), t => t.Name == name);
		}

		/// <summary>
		/// Get the <see cref="InterfaceMapping"/> from the given <see cref="Type"/>.
		/// </summary>
		/// <param name="type">The <see cref="Type"/> to get the interface from.</param>
		/// <param name="name">The name of the interface to get.</param>
		/// <returns>An <see cref="InterfaceMapping"/> of the interface.</returns>
		public static InterfaceMapping GetInterfaceMaping(Type type, string name)
		{
			return type.GetInterfaceMap(GetInterface(type, name));
		}

		/// <summary>
		/// Determines if a <see cref="Type"/> is a concrete type.
		/// </summary>
		/// <param name="type">The <see cref="Type"/> to check.</param>
		/// <returns></returns>
		public static bool IsConcreteType(Type type)
		{
			return IsClass(type) && !type.IsAbstract && !IsGeneric(type) && type.IsPublic && !type.IsEnum && !typeof(Attribute).IsAssignableFrom(type);
		}

		/// <summary>
		/// Determines if a <see cref="Type"/> is a collection.
		/// </summary>
		/// <param name="type">The <see cref="Type"/> to check.</param>
		/// <returns>True if the type is a collection, False if it is not.</returns>
		public static bool IsCollection(Type type)
		{
			return typeof(ICollection).IsAssignableFrom(type) || typeof(ICollection<>).IsAssignableFrom(type);
		}

		/// <summary>
		/// Determines if a <see cref="Type"/> is enumerable.
		/// </summary>
		/// <param name="type">The <see cref="Type"/> to check.</param>
		/// <returns>True if the type is a enumerable, False if it is not.</returns>
		public static bool IsEnumerable(Type type)
		{
			return typeof(IEnumerable).IsAssignableFrom(type) || typeof(IEnumerable<>).IsAssignableFrom(type);
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is the type of a class.
		/// </summary>
		/// <param name="type">The <see cref="Type"/></param> to check.
		/// <returns>True if the <see cref="Type"/> is a class type, False if it is not.</returns>
		public static bool IsClass(Type type)
		{
			return type.IsClass;
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is a child array.
		/// </summary>
		/// <param name="type">The <see cref="Type"/> to check.</param>
		/// <returns>True if it is an array, False if it is not.</returns>
		public static bool IsChildArray(Type type)
		{
			return (type.IsArray && !IsSimple(type.GetElementType()));
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is an enum.
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		public static bool IsEnum(Type type)
		{
			return type.IsEnum;
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is a generic type.
		/// </summary>
		/// <param name="pluggedType"></param>
		/// <returns></returns>
		public static bool IsGeneric(Type pluggedType)
		{
			return (pluggedType.IsGenericType || pluggedType.IsGenericTypeDefinition || pluggedType.ContainsGenericParameters);
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is a primitive type.
		/// </summary>
		/// <param name="type">The <see cref="Type"/> to check.</param>
		/// <returns>True if it is a primitive type, False if it is not.</returns>
		public static bool IsPrimitive(Type type)
		{
			return ((type.IsPrimitive && !IsString(type)) && (type != typeof(IntPtr)));
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is an array of primitive types.
		/// </summary>
		/// <param name="type">The <see cref="Type"/> to check.</param>
		/// <returns>True if it is a primitive array, False if it is not.s</returns>
		public static bool IsPrimitiveArray(Type type)
		{
			return (type.IsArray && IsSimple(type.GetElementType()));
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is a simple type.
		/// (examples: <see cref="bool"/>, <see cref="String"/>, <see cref="int"/>, is an enum, ect...
		/// </summary>
		/// <param name="type">The <see cref="Type"/> to check.</param>
		/// <returns>True if it is a simple type, False if it is not.</returns>
		public static bool IsSimple(Type type)
		{
			if (!type.IsPrimitive && !IsString(type))
			{
				return IsEnum(type);
			}

			return true;
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is of type <see cref="String"/>.
		/// </summary>
		/// <param name="type">The <see cref="Type"/> to check.</param>
		/// <returns>True if it is a <see cref="string"/>, False if it is not.</returns>
		public static bool IsString(Type type)
		{
			return type.Equals(typeof(string));
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> has no public constructors.
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		public static bool HasNoPublicConstructors(Type type)
		{
			return (type.GetConstructors().Length == 0);
		}

		#region IReflect Members

		/// <summary>
		/// Returns the <see cref="T:System.Reflection.FieldInfo"/> object that corresponds to the specified field and binding flag.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.Reflection.FieldInfo"/> object containing the field information for the named object that meets the search constraints specified in <paramref name="bindingAttr"/>.
		/// </returns>
		/// <param name="name">The name of the field to find. </param><param name="bindingAttr">The binding attributes used to control the search. </param><exception cref="T:System.Reflection.AmbiguousMatchException">The object implements multiple fields with the same name. </exception>
		public FieldInfo GetField(string name, BindingFlags bindingAttr)
		{
			return Type.GetField(name, bindingAttr);
		}

		/// <summary>
		/// Returns an array of <see cref="T:System.Reflection.FieldInfo"/> objects that correspond to all fields of the current class.
		/// </summary>
		/// <returns>
		/// An array of <see cref="T:System.Reflection.FieldInfo"/> objects containing all the field information for this reflection object that meets the search constraints specified in <paramref name="bindingAttr"/>.
		/// </returns>
		/// <param name="bindingAttr">The binding attributes used to control the search. </param>
		public FieldInfo[] GetFields(BindingFlags bindingAttr)
		{
			return Type.GetFields(bindingAttr);
		}

		/// <summary>
		/// Retrieves an array of <see cref="T:System.Reflection.MemberInfo"/> objects corresponding to all public members or to all members that match a specified name.
		/// </summary>
		/// <returns>
		/// An array of <see cref="T:System.Reflection.MemberInfo"/> objects matching the <paramref name="name"/> parameter.
		/// </returns>
		/// <param name="name">The name of the member to find. </param><param name="bindingAttr">The binding attributes used to control the search. </param>
		public MemberInfo[] GetMember(string name, BindingFlags bindingAttr)
		{
			return Type.GetMember(name, bindingAttr);
		}

		/// <summary>
		/// Retrieves an array of <see cref="T:System.Reflection.MemberInfo"/> objects that correspond either to all public members or to all members of the current class.
		/// </summary>
		/// <returns>
		/// An array of <see cref="T:System.Reflection.MemberInfo"/> objects containing all the member information for this reflection object.
		/// </returns>
		/// <param name="bindingAttr">The binding attributes used to control the search. </param>
		public MemberInfo[] GetMembers(BindingFlags bindingAttr)
		{
			return Type.GetMembers(bindingAttr);
		}

		/// <summary>
		/// Retrieves a <see cref="T:System.Reflection.MethodInfo"/> object that corresponds to a specified method under specified search constraints.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.Reflection.MethodInfo"/> object containing the method information, with the match being based on the method name and search constraints specified in <paramref name="bindingAttr"/>.
		/// </returns>
		/// <param name="name">The name of the member to find. </param><param name="bindingAttr">The binding attributes used to control the search. </param><exception cref="T:System.Reflection.AmbiguousMatchException">The object implements multiple methods with the same name. </exception>
		public MethodInfo GetMethod(string name, BindingFlags bindingAttr)
		{
			return Type.GetMethod(name, bindingAttr);
		}

		/// <summary>
		/// Retrieves a <see cref="T:System.Reflection.MethodInfo"/> object corresponding to a specified method, using a <see cref="T:System.Type"/> array to choose from among overloaded methods.
		/// </summary>
		/// <returns>
		/// The requested method that matches all the specified parameters.
		/// </returns>
		/// <param name="name">The name of the member to find. </param><param name="bindingAttr">The binding attributes used to control the search. </param><param name="binder">An object that implements <see cref="T:System.Reflection.Binder"/>, containing properties related to this method. </param><param name="types">An array used to choose among overloaded methods. </param><param name="modifiers">An array of parameter modifiers used to make binding work with parameter signatures in which the types have been modified. </param><exception cref="T:System.Reflection.AmbiguousMatchException">The object implements multiple methods with the same name. </exception>
		public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
		{
			return Type.GetMethod(name, bindingAttr, binder, types, modifiers);
		}

		/// <summary>
		/// Retrieves an array of <see cref="T:System.Reflection.MethodInfo"/> objects with all public methods or all methods of the current class.
		/// </summary>
		/// <returns>
		/// An array of <see cref="T:System.Reflection.MethodInfo"/> objects containing all the methods defined for this reflection object that meet the search constraints specified in <paramref name="bindingAttr"/>.
		/// </returns>
		/// <param name="bindingAttr">The binding attributes used to control the search. </param>
		public MethodInfo[] GetMethods(BindingFlags bindingAttr)
		{
			return Type.GetMethods(bindingAttr);
		}

		/// <summary>
		/// Retrieves an array of <see cref="T:System.Reflection.PropertyInfo"/> objects corresponding to all public properties or to all properties of the current class.
		/// </summary>
		/// <returns>
		/// An array of <see cref="T:System.Reflection.PropertyInfo"/> objects for all the properties defined on the reflection object.
		/// </returns>
		/// <param name="bindingAttr">The binding attribute used to control the search. </param>
		public PropertyInfo[] GetProperties(BindingFlags bindingAttr)
		{
			return Type.GetProperties(bindingAttr);
		}

		/// <summary>
		/// Retrieves a <see cref="T:System.Reflection.PropertyInfo"/> object that corresponds to a specified property with specified search constraints.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.Reflection.PropertyInfo"/> object for the located property, if a property with the specified name was located in this reflection object, or null if the property was not located.
		/// </returns>
		/// <param name="name">The name of the member to find. </param><param name="bindingAttr">The binding attribute used to control the search. </param><param name="binder">An object that implements <see cref="T:System.Reflection.Binder"/>, containing properties related to this method. </param><param name="returnType">The type of the property. </param><param name="types">An array used to choose among overloaded methods with the same name. </param><param name="modifiers">An array used to choose the parameter modifiers. </param>
		public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
		{
			return Type.GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
		}

		/// <summary>
		/// Retrieves a <see cref="T:System.Reflection.PropertyInfo"/> object corresponding to a specified property under specified search constraints.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.Reflection.PropertyInfo"/> object for the located property that meets the search constraints specified in <paramref name="bindingAttr"/>, or null if the property was not located.
		/// </returns>
		/// <param name="name">The name of the property to find. </param><param name="bindingAttr">The binding attributes used to control the search. </param><exception cref="T:System.Reflection.AmbiguousMatchException">The object implements multiple fields with the same name. </exception>
		public PropertyInfo GetProperty(string name, BindingFlags bindingAttr)
		{
			return Type.GetProperty(name, bindingAttr);
		}

		/// <summary>
		/// Invokes a specified member.
		/// </summary>
		/// <returns>
		/// The specified member.
		/// </returns>
		/// <param name="name">The name of the member to find. </param><param name="invokeAttr">One of the <see cref="T:System.Reflection.BindingFlags"/> invocation attributes. The <paramref name="invokeAttr"/> parameter may be a constructor, method, property, or field. A suitable invocation attribute must be specified. Invoke the default member of a class by passing the empty string ("") as the name of the member. </param><param name="binder">One of the <see cref="T:System.Reflection.BindingFlags"/> bit flags. Implements <see cref="T:System.Reflection.Binder"/>, containing properties related to this method. </param><param name="target">The object on which to invoke the specified member. This parameter is ignored for static members. </param><param name="args">An array of objects that contains the number, order, and type of the parameters of the member to be invoked. This is an empty array if there are no parameters. </param><param name="modifiers">An array of <see cref="T:System.Reflection.ParameterModifier"/> objects. This array has the same length as the <paramref name="args"/> parameter, representing the invoked member's argument attributes in the metadata. A parameter can have the following attributes: pdIn, pdOut, pdRetval, pdOptional, and pdHasDefault. These represent [In], [Out], [retval], [optional], and a default parameter, respectively. These attributes are used by various interoperability services. </param><param name="culture">An instance of <see cref="T:System.Globalization.CultureInfo"/> used to govern the coercion of types. For example, <paramref name="culture"/> converts a String that represents 1000 to a Double value, since 1000 is represented differently by different cultures. If this parameter is null, the <see cref="T:System.Globalization.CultureInfo"/> for the current thread is used. </param><param name="namedParameters">A String array of parameters. </param><exception cref="T:System.ArgumentException"><paramref name="invokeAttr"/> is <see cref="F:System.Reflection.BindingFlags.CreateInstance"/> and another bit flag is also set. </exception><exception cref="T:System.ArgumentException"><paramref name="invokeAttr"/> is not <see cref="F:System.Reflection.BindingFlags.CreateInstance"/> and <paramref name="name"/> is null. </exception><exception cref="T:System.ArgumentException"><paramref name="invokeAttr"/> is not an invocation attribute from <see cref="T:System.Reflection.BindingFlags"/>. </exception><exception cref="T:System.ArgumentException"><paramref name="invokeAttr"/> specifies both get and set for a property or field. </exception><exception cref="T:System.ArgumentException"><paramref name="invokeAttr"/> specifies both a field set and an Invoke method. <paramref name="args"/> are provided for a field get. </exception><exception cref="T:System.ArgumentException">More than one argument is specified for a field set. </exception><exception cref="T:System.MissingFieldException">The field or property cannot be found. </exception><exception cref="T:System.MissingMethodException">The method cannot be found. </exception><exception cref="T:System.Security.SecurityException">A private member is invoked without the necessary <see cref="T:System.Security.Permissions.ReflectionPermission"/>. </exception>
		public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
		{
			return Type.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
		}

		#endregion

		#endregion
	}

	/// <summary>
	/// Provides helper methods for working with <see cref="Type"/>s.
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class TypeHelper<T> : IReflect
	{
		#region Fields

		private readonly Type _type;

		#endregion

		#region Constructors

		/// <summary>
		/// The constructor for the <see cref="TypeHelper"/> class.
		/// </summary>
		/// <param name="entity"></param>
		public TypeHelper(T entity)
		{
			_type = typeof(T);
			Entity = entity;
		}

		#endregion

		#region Properties

		/// <summary>
		/// The current type to provide helper methods for.
		/// </summary>
		public T Entity { get; protected set; }

		#region IReflect Methods

		/// <summary>
		/// Gets the underlying type that represents the <see cref="T:System.Reflection.IReflect"/> object.
		/// </summary>
		/// <returns>
		/// The underlying type that represents the <see cref="T:System.Reflection.IReflect"/> object.
		/// </returns>
		public Type UnderlyingSystemType
		{
			get
			{
				return _type.UnderlyingSystemType;
			}
		}

		#endregion

		#endregion

		#region Methods

		///<summary>
		/// Determines if a <see cref="MethodInfo"/> or <see cref="ConstructorInfo"/> have any parameters.
		///</summary>
		///<returns>True if the method or constructor has no parameters and False if it does.</returns>
		public bool IsDefault(string methodName)
		{
			return TypeHelper.IsDefault(_type.GetMethod(methodName));
		}

		/// <summary>
		/// Gets the <see cref="Type"/> based off the given name.
		/// </summary>
		/// <returns>The object's <see cref="Type"/>.</returns>
		public Type GeType()
		{
			return _type;
		}

		/// <summary>
		/// Gets a specific type of interface from the given <see cref="MemberInfo"/>.
		/// </summary>
		/// <typeparam name="TAttribute">The type of interface to get.</typeparam>
		/// <returns>
		/// The <typeparamref name="TAttribute"/> attribute, or the default
		/// value if no attribute of <typeparamref name="TAttribute"/> exists.
		/// </returns>
		public TAttribute GetAttribute<TAttribute>()
		{
			TAttribute[] attributes = GetAttributes<TAttribute>();
			return !attributes.HasElements() ? attributes[0] : default(TAttribute);
		}

		/// <summary>
		/// Get an array of attributes from the given <see cref="MemberInfo"/>.
		/// </summary>
		/// <typeparam name="TAttribute">The type of attributes to retrieve.</typeparam>
		/// <returns>An array of <typeparamref name="TAttribute"/> attributes.</returns>
		public TAttribute[] GetAttributes<TAttribute>()
		{
			return _type.GetCustomAttributes(typeof(TAttribute), true) as TAttribute[];
		}

		/// <summary>
		/// Gets the interfaces for a given <see cref="Type"/>.
		/// </summary>
		/// <returns>An array of <see cref="Type"/>.</returns>
		public Type[] GetInterfaces()
		{
			return _type.GetInterfaces();
		}

		/// <summary>
		/// Gets an interface from the given type by name.
		/// </summary>
		/// <param name="name">The name of the interface to get.</param>
		/// <returns>The <see cref="Type"/> of interface.</returns>
		public Type GetInterface(string name)
		{
			return Array.Find(GetInterfaces(), t => t.Name == name);
		}

		/// <summary>
		/// Get the <see cref="InterfaceMapping"/> from the given <see cref="Type"/>.
		/// </summary>
		/// <param name="name">The name of the interface to get.</param>
		/// <returns>An <see cref="InterfaceMapping"/> of the interface.</returns>
		public InterfaceMapping GetInterfaceMaping(string name)
		{
			return _type.GetInterfaceMap(GetInterface(name));
		}

		/// <summary>
		/// Determines if a <see cref="Type"/> is a concrete type.
		/// </summary>
		/// <returns></returns>
		public bool IsConcreteType()
		{
			return IsClass() && !_type.IsAbstract && !IsGeneric() && _type.IsPublic && !_type.IsEnum && !_type.Inherits(typeof(Attribute));
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is the type of a class.
		/// </summary>
		/// <returns>True if the <see cref="Type"/> is a class type, False if it is not.</returns>
		public bool IsClass()
		{
			return _type.IsClass;
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is a child array.
		/// </summary>
		/// <returns>True if it is an array, False if it is not.</returns>
		public bool IsChildArray()
		{
			return (_type.IsArray && !IsSimple());
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is an enum.
		/// </summary>
		/// <returns></returns>
		public bool IsEnum()
		{
			return _type.IsEnum;
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is a generic type.
		/// </summary>
		/// <returns></returns>
		public bool IsGeneric()
		{
			return _type.IsGenericTypeDefinition || _type.ContainsGenericParameters;
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is a primitive type.
		/// </summary>
		/// <returns>True if it is a primitive type, False if it is not.</returns>
		public bool IsPrimitive()
		{
			return ((_type.IsPrimitive && !IsString()) && (_type != typeof(IntPtr)));
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is an array of primitive types.
		/// </summary>
		/// <returns>True if it is a primitive array, False if it is not.s</returns>
		public bool IsPrimitiveArray()
		{
			return (_type.IsArray && IsSimple());
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is a simple type.
		/// (examples: <see cref="bool"/>, <see cref="String"/>, <see cref="int"/>, is an enum, ect...
		/// </summary>
		/// <returns>True if it is a simple type, False if it is not.</returns>
		public bool IsSimple()
		{
			if (!_type.IsPrimitive && !IsString())
			{
				return IsEnum();
			}

			return true;
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> is of type <see cref="String"/>.
		/// </summary>
		/// <returns>True if it is a <see cref="string"/>, False if it is not.</returns>
		public bool IsString()
		{
			return _type.Equals(typeof(string));
		}

		/// <summary>
		/// Determines if the <see cref="Type"/> has no public constructors.
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		public bool HasNoPublicConstructors(Type type)
		{
			return (_type.GetConstructors().Length == 0);
		}

		#region IReflect Members

		/// <summary>
		/// Returns the <see cref="T:System.Reflection.FieldInfo"/> object that corresponds to the specified field and binding flag.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.Reflection.FieldInfo"/> object containing the field information for the named object that meets the search constraints specified in <paramref name="bindingAttr"/>.
		/// </returns>
		/// <param name="name">The name of the field to find. </param><param name="bindingAttr">The binding attributes used to control the search. </param><exception cref="T:System.Reflection.AmbiguousMatchException">The object implements multiple fields with the same name. </exception>
		public FieldInfo GetField(string name, BindingFlags bindingAttr)
		{
			return _type.GetField(name, bindingAttr);
		}

		/// <summary>
		/// Returns an array of <see cref="T:System.Reflection.FieldInfo"/> objects that correspond to all fields of the current class.
		/// </summary>
		/// <returns>
		/// An array of <see cref="T:System.Reflection.FieldInfo"/> objects containing all the field information for this reflection object that meets the search constraints specified in <paramref name="bindingAttr"/>.
		/// </returns>
		/// <param name="bindingAttr">The binding attributes used to control the search. </param>
		public FieldInfo[] GetFields(BindingFlags bindingAttr)
		{
			return _type.GetFields(bindingAttr);
		}

		/// <summary>
		/// Retrieves an array of <see cref="T:System.Reflection.MemberInfo"/> objects corresponding to all public members or to all members that match a specified name.
		/// </summary>
		/// <returns>
		/// An array of <see cref="T:System.Reflection.MemberInfo"/> objects matching the <paramref name="name"/> parameter.
		/// </returns>
		/// <param name="name">The name of the member to find. </param><param name="bindingAttr">The binding attributes used to control the search. </param>
		public MemberInfo[] GetMember(string name, BindingFlags bindingAttr)
		{
			return _type.GetMember(name, bindingAttr);
		}

		/// <summary>
		/// Retrieves an array of <see cref="T:System.Reflection.MemberInfo"/> objects that correspond either to all public members or to all members of the current class.
		/// </summary>
		/// <returns>
		/// An array of <see cref="T:System.Reflection.MemberInfo"/> objects containing all the member information for this reflection object.
		/// </returns>
		/// <param name="bindingAttr">The binding attributes used to control the search. </param>
		public MemberInfo[] GetMembers(BindingFlags bindingAttr)
		{
			return _type.GetMembers(bindingAttr);
		}

		/// <summary>
		/// Retrieves a <see cref="T:System.Reflection.MethodInfo"/> object that corresponds to a specified method under specified search constraints.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.Reflection.MethodInfo"/> object containing the method information, with the match being based on the method name and search constraints specified in <paramref name="bindingAttr"/>.
		/// </returns>
		/// <param name="name">The name of the member to find. </param><param name="bindingAttr">The binding attributes used to control the search. </param><exception cref="T:System.Reflection.AmbiguousMatchException">The object implements multiple methods with the same name. </exception>
		public MethodInfo GetMethod(string name, BindingFlags bindingAttr)
		{
			return _type.GetMethod(name, bindingAttr);
		}

		/// <summary>
		/// Retrieves a <see cref="T:System.Reflection.MethodInfo"/> object corresponding to a specified method, using a <see cref="T:System.Type"/> array to choose from among overloaded methods.
		/// </summary>
		/// <returns>
		/// The requested method that matches all the specified parameters.
		/// </returns>
		/// <param name="name">The name of the member to find. </param><param name="bindingAttr">The binding attributes used to control the search. </param><param name="binder">An object that implements <see cref="T:System.Reflection.Binder"/>, containing properties related to this method. </param><param name="types">An array used to choose among overloaded methods. </param><param name="modifiers">An array of parameter modifiers used to make binding work with parameter signatures in which the types have been modified. </param><exception cref="T:System.Reflection.AmbiguousMatchException">The object implements multiple methods with the same name. </exception>
		public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
		{
			return _type.GetMethod(name, bindingAttr, binder, types, modifiers);
		}

		/// <summary>
		/// Retrieves an array of <see cref="T:System.Reflection.MethodInfo"/> objects with all public methods or all methods of the current class.
		/// </summary>
		/// <returns>
		/// An array of <see cref="T:System.Reflection.MethodInfo"/> objects containing all the methods defined for this reflection object that meet the search constraints specified in <paramref name="bindingAttr"/>.
		/// </returns>
		/// <param name="bindingAttr">The binding attributes used to control the search. </param>
		public MethodInfo[] GetMethods(BindingFlags bindingAttr)
		{
			return _type.GetMethods(bindingAttr);
		}

		/// <summary>
		/// Retrieves an array of <see cref="T:System.Reflection.PropertyInfo"/> objects corresponding to all public properties or to all properties of the current class.
		/// </summary>
		/// <returns>
		/// An array of <see cref="T:System.Reflection.PropertyInfo"/> objects for all the properties defined on the reflection object.
		/// </returns>
		/// <param name="bindingAttr">The binding attribute used to control the search. </param>
		public PropertyInfo[] GetProperties(BindingFlags bindingAttr)
		{
			return _type.GetProperties(bindingAttr);
		}

		/// <summary>
		/// Retrieves a <see cref="T:System.Reflection.PropertyInfo"/> object that corresponds to a specified property with specified search constraints.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.Reflection.PropertyInfo"/> object for the located property, if a property with the specified name was located in this reflection object, or null if the property was not located.
		/// </returns>
		/// <param name="name">The name of the member to find. </param><param name="bindingAttr">The binding attribute used to control the search. </param><param name="binder">An object that implements <see cref="T:System.Reflection.Binder"/>, containing properties related to this method. </param><param name="returnType">The type of the property. </param><param name="types">An array used to choose among overloaded methods with the same name. </param><param name="modifiers">An array used to choose the parameter modifiers. </param>
		public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
		{
			return _type.GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
		}

		/// <summary>
		/// Retrieves a <see cref="T:System.Reflection.PropertyInfo"/> object corresponding to a specified property under specified search constraints.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.Reflection.PropertyInfo"/> object for the located property that meets the search constraints specified in <paramref name="bindingAttr"/>, or null if the property was not located.
		/// </returns>
		/// <param name="name">The name of the property to find. </param><param name="bindingAttr">The binding attributes used to control the search. </param><exception cref="T:System.Reflection.AmbiguousMatchException">The object implements multiple fields with the same name. </exception>
		public PropertyInfo GetProperty(string name, BindingFlags bindingAttr)
		{
			return _type.GetProperty(name, bindingAttr);
		}

		/// <summary>
		/// Invokes a specified member.
		/// </summary>
		/// <returns>
		/// The specified member.
		/// </returns>
		/// <param name="name">The name of the member to find. </param><param name="invokeAttr">One of the <see cref="T:System.Reflection.BindingFlags"/> invocation attributes. The <paramref name="invokeAttr"/> parameter may be a constructor, method, property, or field. A suitable invocation attribute must be specified. Invoke the default member of a class by passing the empty string ("") as the name of the member. </param><param name="binder">One of the <see cref="T:System.Reflection.BindingFlags"/> bit flags. Implements <see cref="T:System.Reflection.Binder"/>, containing properties related to this method. </param><param name="target">The object on which to invoke the specified member. This parameter is ignored for static members. </param><param name="args">An array of objects that contains the number, order, and type of the parameters of the member to be invoked. This is an empty array if there are no parameters. </param><param name="modifiers">An array of <see cref="T:System.Reflection.ParameterModifier"/> objects. This array has the same length as the <paramref name="args"/> parameter, representing the invoked member's argument attributes in the metadata. A parameter can have the following attributes: pdIn, pdOut, pdRetval, pdOptional, and pdHasDefault. These represent [In], [Out], [retval], [optional], and a default parameter, respectively. These attributes are used by various interoperability services. </param><param name="culture">An instance of <see cref="T:System.Globalization.CultureInfo"/> used to govern the coercion of types. For example, <paramref name="culture"/> converts a String that represents 1000 to a Double value, since 1000 is represented differently by different cultures. If this parameter is null, the <see cref="T:System.Globalization.CultureInfo"/> for the current thread is used. </param><param name="namedParameters">A String array of parameters. </param><exception cref="T:System.ArgumentException"><paramref name="invokeAttr"/> is <see cref="F:System.Reflection.BindingFlags.CreateInstance"/> and another bit flag is also set. </exception><exception cref="T:System.ArgumentException"><paramref name="invokeAttr"/> is not <see cref="F:System.Reflection.BindingFlags.CreateInstance"/> and <paramref name="name"/> is null. </exception><exception cref="T:System.ArgumentException"><paramref name="invokeAttr"/> is not an invocation attribute from <see cref="T:System.Reflection.BindingFlags"/>. </exception><exception cref="T:System.ArgumentException"><paramref name="invokeAttr"/> specifies both get and set for a property or field. </exception><exception cref="T:System.ArgumentException"><paramref name="invokeAttr"/> specifies both a field set and an Invoke method. <paramref name="args"/> are provided for a field get. </exception><exception cref="T:System.ArgumentException">More than one argument is specified for a field set. </exception><exception cref="T:System.MissingFieldException">The field or property cannot be found. </exception><exception cref="T:System.MissingMethodException">The method cannot be found. </exception><exception cref="T:System.Security.SecurityException">A private member is invoked without the necessary <see cref="T:System.Security.Permissions.ReflectionPermission"/>. </exception>
		public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
		{
			return _type.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
		}

		#endregion

		#endregion
	}
}